
#include "include/klib.h"
#include "include/irq.h"
#include "include/keymap.h"
#include "include/tty.h"
#include "include/keyboard.h"



static KB_INPUT kb_in;



static int shift_l;
static int shift_r;
static int alt_l;
static int alt_r;
static int ctrl_l;
static int ctrl_r;

u8 get_byte_from_kb_buf()
{
    u8 scan_code;
    while (kb_in.count <= 0);
    disable_int();
    scan_code = *(kb_in.p_tail);
    kb_in.p_tail++;
    if (kb_in.p_tail == kb_in.buf + KB_IN_BYTES)
    {
        kb_in.p_tail = kb_in.buf;
    }
    kb_in.count--;
    enable_int();
    return scan_code;
}

u8 scan_code;
u32 code_with_E0;
u32 key;
u32* keyrow;
u8 column;

void keyboard_read(TTY *p_tty)
{
    
    char output[2] = {0};
    int make;
    key = 0;
    if (kb_in.count > 0)
    {
        code_with_E0 = 0;
        scan_code = get_byte_from_kb_buf();
        if (scan_code == 0xE1) 
        {
            /* PASS */
        } 
        else if (scan_code == 0xE0) 
        {
            scan_code = get_byte_from_kb_buf();
            if (key == 0)
            {
                code_with_E0 = 1;
            }
        }
        make = (scan_code & FLAG_BREAK ? 0:1); 
        keyrow = &keymap[(scan_code&0x7F)*MAP_COLS];
        column = 0;   
        if (shift_l || shift_r)
        {
            column = 1;
        }
        if (code_with_E0)
        {
            column = 2;
            disp_u32(column, 0x000f0B00);
        }
        key = keyrow[column];
        switch (key)
        {
        case SHIFT_L:
            shift_l = make;
            break;
        case SHIFT_R:
            shift_r = make;
            break;
        default:
            if (!make)
            {
                key = 0;
            }
            break;
        }
            
        if (make) 
        {
            key |= shift_l ? FLAG_SHIFT_L : 0;
            key |= shift_r ? FLAG_SHIFT_R : 0;
            key |= ctrl_l ? FLAG_CTRL_L : 0;
            key |= ctrl_r ? FLAG_CTRL_R : 0;
            key |= alt_l ? FLAG_ALT_L : 0;
            key |= alt_r ? FLAG_ALT_R : 0;
            in_process(p_tty,key);
        }   
    }
}

void keyboard_handler()
{
    u8 scan_code = in_byte(0x60);
    
    if (kb_in.count < KB_IN_BYTES) 
    {
        *(kb_in.p_head) = scan_code;
        kb_in.p_head++;
        if (kb_in.p_head == kb_in.buf + KB_IN_BYTES)
        {
            kb_in.p_head = kb_in.buf;
        }
        kb_in.count++;
    }
}
void init_keyboard()
{
    kb_in.count = 0;
    kb_in.p_head = kb_in.p_tail = kb_in.buf;
    shift_l = 0;
    shift_r = 0;
    put_irq_handler(1, keyboard_handler);
    enable_irq(1);
}